#pragma once

#include <cassert>
#include <type_traits>
#include <utility>

namespace util {

template <typename T, int Size> struct RingBuffer {
  static_assert(Size > 0, "size must be greater than 0");
  static_assert(std::is_trivially_destructible_v<T>,
                "T must be trivilly destructivle");

  template<typename... Args>
  void put(Args... args) {
    items[free] = T(std::forward<Args>(args)...);
    if (++free >= Size) {
      free = 0;
    }
    assert(free != occupied);
  }

  T &current() {
    assert(free != occupied);
    return items[occupied];
  }

  void pop() {
    assert(free != occupied);
    if (++occupied >= Size) {
      occupied = 0;
    }
  }

  bool emtpy() { return occupied == free; }

//private:
  T items[Size];
  int occupied = 0;
  int free = 0;
};

} // namespace util
